package com.hundsun.cprs.yyt.service.trade.service.impl;

import java.text.MessageFormat;
import java.util.List;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;

import com.hundsun.cprs.yyt.common.base.BaseService;
import com.hundsun.cprs.yyt.common.exception.ServiceException;
import com.hundsun.cprs.yyt.common.redis.RedisDistributedLock;
import com.hundsun.cprs.yyt.service.rabbit.RoutingKeyConstants;
import com.hundsun.cprs.yyt.service.trade.dao.TradeRollbackFlowDao;
import com.hundsun.cprs.yyt.service.trade.domain.TradeEntrust;
import com.hundsun.cprs.yyt.service.trade.domain.TradeRollbackFlow;
import com.hundsun.cprs.yyt.service.trade.domain.query.TradeRollbackFlowQuery;
import com.hundsun.cprs.yyt.service.trade.enums.EnumEntustRollbackStatus;
import com.hundsun.cprs.yyt.service.trade.enums.EnumTradeEntrustStatus;
import com.hundsun.cprs.yyt.service.trade.service.TradeEntrustRollbackService;

@Service
public class TradeEntrustRollbackServiceImpl extends BaseService implements TradeEntrustRollbackService {
    
    private static final String APPLY_ROLLBACK_KEY = "YYT:Entrust:{0}:Apply_rollback_lock";

    @Autowired
    private TradeRollbackFlowDao tradeRollbackFlowDao;
    
    @Autowired
    private RedisDistributedLock redisLock;
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    @Override
    public void selectByPage(TradeRollbackFlowQuery query) {
       List<TradeRollbackFlow> result = tradeRollbackFlowDao.selectByQuery(query);
       query.compatible(result);
    }

    @Override
    public TradeRollbackFlow applyRollbackEntrust(TradeEntrust entrust) {
        Assert.notNull(entrust, "委托单信息必填");
        
        /*if (EnumTradeEntrustStatus.COMMITED.getStatus() != entrust.getEntrustStatus()) {
            throw new ServiceException("委托单状态未处于委售中或已部分成交,不允许撤回.");
        }*/
        
        //查询该委托单是否已存在撤回，若存在直接返回
        TradeRollbackFlow existRecord;
        String applyLock = MessageFormat.format(APPLY_ROLLBACK_KEY, entrust.getId());
        try {
            redisLock.lock(applyLock);
            existRecord = tradeRollbackFlowDao.selectByEntrustIdAndRollbackStatus(entrust.getId(), EnumEntustRollbackStatus.COMMITED.getCode());
            if (existRecord == null) {
                DefaultTransactionDefinition defintion = new DefaultTransactionDefinition();
                defintion.setPropagationBehavior(Propagation.REQUIRES_NEW.value());
                defintion.setIsolationLevel(Isolation.READ_COMMITTED.value());
                TransactionStatus status = transactionTemplate.getTransactionManager().getTransaction(defintion);
                try{
                    TradeRollbackFlow rollbackFlow = new TradeRollbackFlow();
                    rollbackFlow.setEntrustId(entrust.getId());
                    rollbackFlow.setEntrustNo(entrust.getEntrustNo());
                    rollbackFlow.setRollbackStatus(EnumEntustRollbackStatus.COMMITED.getCode());
                    rollbackFlow.setRollbackAmount(0l);
                    tradeRollbackFlowDao.insert(rollbackFlow);
                    existRecord = rollbackFlow;
                    transactionTemplate.getTransactionManager().commit(status);
                } catch(Exception e) {
                    transactionTemplate.getTransactionManager().rollback(status);
                    throw e;
                }
                // 新创建的发送通知
                // 通过MQ方式通知匹配中心处理
                rabbitTemplate.convertAndSend(RoutingKeyConstants.YYT_TRADE_ENTRUST_ROLLBACK, existRecord);
            }
        } finally {
            redisLock.releaseLock(applyLock);
        }
        return existRecord;
    }

    @Override
    public void updateRollbackFlow(TradeRollbackFlow flow) {
        tradeRollbackFlowDao.updateByPrimaryKey(flow);
    }

}
